import { createRoot } from "react-dom/client";
import Alert from "../components/ui/Alert";
import type { AlertStatus, AlertVariant } from "../components/ui/Alert";

// 简化的提示选项接口
interface AlertOptions {
  variant?: AlertVariant;
  duration?: number;
}

/**
 * 全局提示服务
 *
 * 用于在应用中的任何位置显示提示信息，无需在每个组件中单独导入Alert
 * 使用 Material-UI Alert 组件的默认样式
 * @author BelovedLYC
 */
class AlertService {
  // 跟踪当前活跃的提示消息
  private activeAlerts: Map<
    string,
    {
      timer: ReturnType<typeof setTimeout>;
      containerElement: HTMLElement;
    }
  > = new Map();

  /**
   * 显示提示
   * @param status 提示类型: success | info | warning | error
   * @param message 提示内容
   * @param options 可选配置项：样式变体、显示时长等
   */
  show(status: AlertStatus, message: string, options: AlertOptions = {}) {
    const { variant = "standard", duration = 3000 } = options;

    // 创建唯一的alert key (状态+消息)
    const alertKey = `${status}:${message}`;

    // 如果已经存在相同的提示，则清除旧的计时器但不显示新的提示
    if (this.activeAlerts.has(alertKey)) {
      const existing = this.activeAlerts.get(alertKey);
      if (existing) {
        clearTimeout(existing.timer);
        // 更新计时器但保留同一个DOM元素
        const newTimer = setTimeout(() => {
          this.removeAlert(alertKey);
        }, duration);
        this.activeAlerts.set(alertKey, {
          ...existing,
          timer: newTimer,
        });
        return;
      }
    }

    // 创建容器元素
    const containerElement = document.createElement("div");
    document.body.appendChild(containerElement);

    // 创建React根节点
    const root = createRoot(containerElement);

    // 设置超时以移除alert
    const timer = setTimeout(() => {
      this.removeAlert(alertKey);
    }, duration);

    // 存储alert信息
    this.activeAlerts.set(alertKey, {
      timer,
      containerElement,
    });

    // 渲染Alert组件
    root.render(
      <Alert
        status={status}
        message={message}
        variant={variant}
        duration={duration}
        onClose={() => {
          this.removeAlert(alertKey);
        }}
      />
    );
  }

  /**
   * 移除alert
   * @param alertKey alert的唯一键
   */
  private removeAlert(alertKey: string) {
    const alertInfo = this.activeAlerts.get(alertKey);
    if (alertInfo) {
      const { containerElement, timer } = alertInfo;

      // 清除计时器
      clearTimeout(timer);

      // 从DOM中移除容器
      if (containerElement.parentNode) {
        setTimeout(() => {
          if (containerElement.parentNode) {
            containerElement.parentNode.removeChild(containerElement);
          }
        }, 300); // 动画时间
      }

      // 从活跃Map中移除
      this.activeAlerts.delete(alertKey);
    }
  }

  /**
   * 显示成功提示
   * @param message 提示内容
   * @param options 可选配置项
   */
  success(message: string, options?: AlertOptions) {
    this.show("success", message, options);
  }

  /**
   * 显示信息提示
   * @param message 提示内容
   * @param options 可选配置项
   */
  info(message: string, options?: AlertOptions) {
    this.show("info", message, options);
  }

  /**
   * 显示警告提示
   * @param message 提示内容
   * @param options 可选配置项
   */
  warning(message: string, options?: AlertOptions) {
    this.show("warning", message, options);
  }

  /**
   * 显示错误提示
   * @param message 提示内容
   * @param options 可选配置项
   */
  error(message: string, options?: AlertOptions) {
    this.show("error", message, options);
  }

  /**
   * 显示标准样式的提示（默认）
   * @param status 提示类型
   * @param message 提示内容
   * @param duration 显示时长（毫秒）
   */
  standard(status: AlertStatus, message: string, duration?: number) {
    this.show(status, message, { variant: "standard", duration });
  }

  /**
   * 显示填充样式的提示
   * @param status 提示类型
   * @param message 提示内容
   * @param duration 显示时长（毫秒）
   */
  filled(status: AlertStatus, message: string, duration?: number) {
    this.show(status, message, { variant: "filled", duration });
  }

  /**
   * 显示轮廓样式的提示
   * @param status 提示类型
   * @param message 提示内容
   * @param duration 显示时长（毫秒）
   */
  outlined(status: AlertStatus, message: string, duration?: number) {
    this.show(status, message, { variant: "outlined", duration });
  }
}

// 创建单例实例
const alertService = new AlertService();

export default alertService;
